#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>

#define ACCOUNT_LENGTH 10

// 服务器配置信息
#define SERVER_IP "192.168.2.77"
#define SERVER_PORT 60000

// 用户链表结构体
struct account_info
{
    char a[ACCOUNT_LENGTH + 1];     // 账号
    char user_name[30];             // 用户名
    char password[30];              // 密码
    struct sockaddr_in client_addr; // 地址结构体
};

// 登录信息结构体
struct login_info
{
    char identifier[30]; // 用户名或账号
    char password[30];
};

// 在线用户信息
struct online_user
{
    char account[ACCOUNT_LENGTH + 1];
    char username[30];
    struct online_user *next;
};

// 消息结构体
struct chat_message
{
    char sender[ACCOUNT_LENGTH + 1];
    char recipient[ACCOUNT_LENGTH + 1];
    char content[256];
};

// 线程参数结构体
struct thread_args
{
    int socket_fd;
    int *is_running;
    struct online_user **online_list; // 在线用户列表
};

// 全局运行状态
int is_running = 1;

void print_online_users(struct online_user *list)
{
    printf("\n=== 在线用户 ===\n");
    struct online_user *current = list;
    int count = 1;

    while (current != NULL)
    {
        printf("%d. %s (%s)\n", count, current->username, current->account);
        current = current->next;
        count++;
    }
    printf("================\n");
    printf("> ");
    fflush(stdout);
}

void add_online_user(struct online_user **list, const char *account, const char *username)
{
    struct online_user *new_user = malloc(sizeof(struct online_user));
    if (!new_user)
    {
        perror("内存分配失败");
        return;
    }

    strncpy(new_user->account, account, ACCOUNT_LENGTH);
    strncpy(new_user->username, username, 29);
    new_user->next = *list;
    *list = new_user;
}

void free_online_users(struct online_user *list)
{
    while (list != NULL)
    {
        struct online_user *temp = list;
        list = list->next;
        free(temp);
    }
}

void register_user(int socket_fd)
{
    send(socket_fd, "REGISTER", 8, 0);

    // 接收响应
    char account[ACCOUNT_LENGTH + 1];
    if (recv(socket_fd, account, sizeof(account), 0) <= 0)
    {
        perror("接收账号失败");
        return;
    }

    char name[30] = {0};
    char password[30] = {0};

    printf("请输入用户名: ");
    fgets(name, sizeof(name), stdin);
    name[strcspn(name, "\n")] = '\0'; // 移除换行符

    printf("请输入密码: ");
    fgets(password, sizeof(password), stdin);
    password[strcspn(password, "\n")] = '\0'; // 移除换行符

    // 构造并发送注册信息
    struct account_info reg_info;
    memset(&reg_info, 0, sizeof(reg_info));

    strncpy(reg_info.a, account, ACCOUNT_LENGTH);
    strncpy(reg_info.user_name, name, sizeof(reg_info.user_name) - 1);
    strncpy(reg_info.password, password, sizeof(reg_info.password) - 1);

    // 发送完整结构体
    if (send(socket_fd, &reg_info, sizeof(reg_info), 0) < 0)
    {
        perror("发送注册信息失败");
    }

    // 等待注册结果
    char response[1024];
    if (recv(socket_fd, response, sizeof(response), 0) > 0)
    {
        printf("\n%s\n", response);
    }
}

int login_user(int socket_fd)
{
    struct login_info login_data;
    memset(&login_data, 0, sizeof(login_data));

    // 发送登录请求
    if (send(socket_fd, "LOGIN", 5, 0) < 0)
    {
        perror("发送登录请求失败");
        return -1;
    }

    printf("请输入用户名或账号: ");
    fgets(login_data.identifier, sizeof(login_data.identifier), stdin);
    login_data.identifier[strcspn(login_data.identifier, "\n")] = '\0';

    printf("请输入密码: ");
    fgets(login_data.password, sizeof(login_data.password), stdin);
    login_data.password[strcspn(login_data.password, "\n")] = '\0';

    // // 发送登录请求
    // if (send(socket_fd, "LOGIN", 5, 0) < 0)
    // {
    //     perror("发送登录请求失败");
    //     return -1;
    // }

    // 发送登录信息
    if (send(socket_fd, &login_data, sizeof(login_data), 0) < 0)
    {
        perror("发送登录信息失败");
        return -1;
    }

    // 接收登录结果
    char response[1024];
    int ret = recv(socket_fd, response, sizeof(response), 0);
    if (ret > 0)
    {
        response[ret] = '\0';
        printf("\n%s\n", response);

        if (strstr(response, "LOGIN_SUCCESS") != NULL)
        {
            printf("登录成功，开始聊天...\n");
            return 0; // 登录成功
        }
    }

    return 1; // 登录失败
}

// 接收服务器消息的线程函数
void *recv_thread_func(void *arg)
{
    struct thread_args *args = (struct thread_args *)arg;
    int socket_fd = args->socket_fd;
    int *is_running = args->is_running;
    struct online_user **online_list = args->online_list;

    char buf[1024];
    int ret;

    while (*is_running)
    {
        memset(buf, 0, sizeof(buf));
        ret = recv(socket_fd, buf, sizeof(buf) - 1, 0);

        if (ret > 0)
        {
            buf[ret] = '\0';

            // 处理登录成功响应
            if (strncmp(buf, "LOGIN_SUCCESS:", 14) == 0)
            {
                char username[30] = {0};
                char account[ACCOUNT_LENGTH + 1] = {0};
                if (sscanf(buf + 14, "%29[^:]:%10s", username, account) == 2)
                {
                    printf("\n=== 登录成功! ===\n");
                    printf("用户名: %s\n", username);
                    printf("账号: %s\n", account);
                    printf("================\n");
                }
                printf("> ");
                fflush(stdout);
            }
            // 处理在线用户列表更新
            if (strncmp(buf, "ONLINE:", 7) == 0)
            {
                char *token = strtok(buf + 7, ":");
                free_online_users(*online_list);
                *online_list = NULL;

                while (token != NULL)
                {
                    char account[ACCOUNT_LENGTH + 1] = {0};
                    char username[30] = {0};

                    // 提取账号和用户名
                    if (sscanf(token, "%10[^,],%29[^\n]", account, username) == 2)
                    {
                        add_online_user(online_list, account, username);
                    }

                    token = strtok(NULL, ":");
                }

                print_online_users(*online_list);
            }
            // 处理私聊消息
            else if (strncmp(buf, "PRIVATE:", 8) == 0)
            {
                char sender[ACCOUNT_LENGTH + 1] = {0};
                char message[256] = {0};

                if (sscanf(buf + 8, "%10[^:]:%255[^\n]", sender, message) == 2)
                {
                    printf("\n[私聊] 来自 %s: %s\n", sender, message);
                    printf("> ");
                    fflush(stdout);
                }
            }
            // 普通消息
            else
            {
                printf("\n%s\n", buf);
                printf("> ");
                fflush(stdout);
            }
        }
        else if (ret == 0)
        {
            printf("\n服务器已断开连接\n");
            *is_running = 0;
            break;
        }
        else
        {
            perror("recv error");
            *is_running = 0;
            break;
        }
    }

    free(arg);
    return NULL;
}

void write_message(int socket_fd, struct online_user *online_list)
{
    printf("\n开始聊天 (输入命令: /list 查看在线用户, /to <账号> <消息> 私聊, /exit 退出)\n");
    printf("> ");
    fflush(stdout);

    while (is_running)
    {
        char input[256] = {0};
        if (fgets(input, sizeof(input), stdin) == NULL)
        {
            continue;
        }

        input[strcspn(input, "\n")] = 0; // 移除换行符

        if (strcmp(input, "/exit") == 0)
        {
            is_running = 0;
            break;
        }
        else if (strcmp(input, "/list") == 0)
        {
            // 请求在线用户列表
            send(socket_fd, "LIST", 4, 0);
            printf("> ");
            fflush(stdout);
        }
        else if (strncmp(input, "/to ", 4) == 0)
        {
            char recipient[ACCOUNT_LENGTH + 1] = {0};
            char message[256] = {0};

            // 解析私聊命令: /to <账号> <消息>
            if (sscanf(input + 4, "%10s %255[^\n]", recipient, message) == 2)
            {
                char formatted_msg[300];
                snprintf(formatted_msg, sizeof(formatted_msg), "PRIVATE:%s:%s", recipient, message);
                send(socket_fd, formatted_msg, strlen(formatted_msg), 0);
            }
            else
            {
                printf("格式错误! 使用: /to <账号> <消息>\n");
                printf("> ");
                fflush(stdout);
            }
        }
        else
        {
            // 发送普通消息
            send(socket_fd, input, strlen(input), 0);
            printf("> ");
            fflush(stdout);
        }
    }
}

int main()
{
    int ret;
    pthread_t recv_thread;
    struct online_user *online_list = NULL; // 在线用户列表

    printf("===== 聊天室客户端 =====\n");

    // 1. 创建套接字
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd < 0)
    {
        perror("socket 创建失败");
        return -1;
    }

    // 2. 设置服务器地址
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);

    // 3. 连接服务器
    ret = connect(socket_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if (ret < 0)
    {
        perror("连接服务器失败");
        close(socket_fd);
        return -1;
    }

    printf("成功连接到服务器 %s:%d\n", SERVER_IP, SERVER_PORT);

    int op = 0;
    int login_success = 0;

    while (!login_success)
    {
        printf("请选择操作: 1.注册, 2.登录, 3.退出\n");
        if (scanf("%d", &op) != 1)
        {
            printf("无效输入\n");
            while (getchar() != '\n')
                ; // 清空输入缓冲区
            continue;
        }
        while (getchar() != '\n')
            ; // 清空输入缓冲区

        switch (op)
        {
        case 1:
            register_user(socket_fd);
            break;
        case 2:
            if (login_user(socket_fd) == 0)
            {
                login_success = 1;
                // 登录成功后立即请求在线用户列表
                send(socket_fd, "LIST", 4, 0);
            }
            break;
        case 3:
            close(socket_fd);
            return 0;
        default:
            printf("无效选择\n");
        }
    }

    // 准备线程参数
    struct thread_args *args = malloc(sizeof(struct thread_args));
    if (!args)
    {
        perror("内存分配失败");
        close(socket_fd);
        return -1;
    }
    args->socket_fd = socket_fd;
    args->is_running = &is_running;
    args->online_list = &online_list;

    // 创建接收线程
    ret = pthread_create(&recv_thread, NULL, recv_thread_func, args);
    if (ret != 0)
    {
        perror("无法创建接收线程");
        free(args);
        close(socket_fd);
        return -1;
    }

    //  进入聊天模式
    write_message(socket_fd, online_list);

    // 清理资源
    printf("\n正在退出...\n");
    is_running = 0;

    // 关闭套接字
    close(socket_fd);

    // 等待接收线程结束
    pthread_join(recv_thread, NULL);

    // 释放在线用户列表
    free_online_users(online_list);

    printf("已退出聊天室\n");
    return 0;
}